#include "network_socket.h"
#include "user_socket.h"
#include "user_data.h"
#include "version.h"

#include <pthread.h>


static SOCKET_DEVICE_STRUCT local_device_info = {0};




static int socket_cmd_send_fd = -1;
static int socket_cmd_recv_fd = -1;

static int socket_audio_send_fd = -1;
static int socket_audio_recv_fd = -1;
static int socket_video_send_fd = -1;
static int socket_video_recv_fd = -1;









static int discover_back_count = 0;
static void send_cmd_discover_fun(socket_cmd_send_device_struct *info){
    discover_back_count = 0;
}


static void recv_cmd_discover_fun(socket_cmd_send_device_struct *info){
    user_socket_cmd_send_format(SOCKET_CMD_DISCOVER_BACK, 0, 0, local_device_info.byname, info->addr, 0xFFFFFFFF);
}

static void recv_cmd_discover_back_fun(socket_cmd_send_device_struct *info){
    
}


static socket_cmd_recv_struct socket_cmd_recv_group[] = {
    {"discover ",       SOCKET_CMD_DISCOVER,        send_cmd_discover_fun,  recv_cmd_discover_fun},
    {"discover back ",  SOCKET_CMD_DISCOVER_BACK,   NULL,                   recv_cmd_discover_back_fun},
};

/**
 * @brief  刷新本地设备名称
 * @date   2023-10-23 16:31:43
 * @author xiaole
 * @param  type [0]-doorbell [1]-device
 * @param  build
 * @param  floor
 * @param  index
 * @note
 */
void local_device_byname_refresh(char type,int unit,int floor, int index){
    snprintf(local_device_info.byname, sizeof(local_device_info.byname), "%s %d-%d-%d", DEVICE_BYNAME,unit, floor, index);

    local_device_info.base  = 100;
    local_device_info.type  = type;
    local_device_info.unit  = unit;
    local_device_info.floor = floor;
    local_device_info.index = index;
    local_device_info.identifier = (type&0xFF) << 24 | (unit&0xFF) << 16 | (floor&0xFF) << 8 | (index&0xFF);

    char buf[20] = {0};
    user_socket_network_card_get_ip(NETWORK_CARD_NAME, buf, NULL, NULL);
    sscanf(buf,"%d.%d.%d.%d", &local_device_info.ip[3], &local_device_info.ip[2], &local_device_info.ip[1], &local_device_info.ip[0]);


}






/**
 * @brief  网络 网卡初始化
 * @date   2023-10-23 16:35:44
 * @author xiaole
 * @param  type [0]-门铃    有1个网卡, 不需要搭建网桥
 * @param  type [1]-室内机  有两个网卡, 搭建网桥
 * @note
 */
static void network_card_init(char type){
    char cmd[128] = {0};

    if(type == SOCKET_DEVICE_TYPE_INDOOR){
        system("ip link del name " NETWORK_CARD_NAME " type bridge");
        system("ip link add name " NETWORK_CARD_NAME " type bridge");
        system("ip link set " NETWORK_CARD_NAME " up");
        system("ip link set dev eth0 master " NETWORK_CARD_NAME);
        system("ip link set dev eth1 master " NETWORK_CARD_NAME);
        system("ifconfig eth0 0.0.0.0 promisc");
        system("ifconfig eth1 0.0.0.0 promisc");
        system("ip addr flush dev br0");


        sprintf(cmd, "ip addr add dev %s %d.%d.%d.%d/8", NETWORK_CARD_NAME, local_device_info.base, local_device_info.unit, local_device_info.floor, local_device_info.index);
        system(cmd);

        system("route add -net 224.0.0.0 netmask 240.0.0.0 " NETWORK_CARD_NAME);

    }else{
        sprintf(cmd, "ifconfig eth0 %d.%d.%d.%d netmask 255.0.0.0 ", local_device_info.base, local_device_info.unit, local_device_info.floor, local_device_info.index);
        system(cmd);
        printf("%s\n", cmd);
        system("route add -net 224.0.0.0 netmask 240.0.0.0 eth0");

    }

}

static int socket_cmd_send_init(){
    socket_cmd_send_fd = user_socket_udp_open(SOCKET_GROUP_PORT);
    if (socket_cmd_send_fd < 0){
        return -1;
    }

    if (user_socket_set_ip_multicast_loop(socket_cmd_send_fd, 0) < 0){
        return -1;
    }

    if (user_socket_set_bindtodevice(socket_cmd_send_fd, NETWORK_CARD_NAME) < 0){
        return -1;
    }



    return 1;
}


static int socket_cmd_recv_init(){
    socket_cmd_recv_fd = user_socket_udp_open(SOCKET_GROUP_PORT);
    if (socket_cmd_recv_fd < 0){
        return -1;
    }

    user_socket_bind(socket_cmd_recv_fd, SOCKET_GROUP_PORT, 0);

    if (user_socket_set_ip_add_memership(socket_cmd_recv_fd, SOCKET_GROUP_IP) < 0){
        return -1;
    }

    if (user_socket_set_bindtodevice(socket_cmd_recv_fd, NETWORK_CARD_NAME) < 0){
        return -1;
    }



    return 1;
}


/**
 * @brief  发送指令打包格式化
 * @date   2023-10-23 17:16:54
 * @author xiaole
 * @param  pdata
 * @param  cmd
 * @param  arg1
 * @param  arg2
 * @param  text
 * @return int
 * @note
 */
int user_socket_cmd_send_format(char cmd, unsigned int arg1, unsigned int arg2, const char *text, const char *addr,unsigned int recvArg){
    char pdata[CMD_PACKAGE_LEN] = {0};
    socket_cmd_send_device_struct info = {0};
    info.cmd  = cmd;
    info.arg1 = arg1;
    info.arg2 = arg2;

    int i = 0;

    pdata[i++] = SOCKET_CMD_START;    /* start */
    pdata[i++] = cmd;

    pdata[i++] = ((arg1 & 0xFF000000) >> 24);
    pdata[i++] = ((arg1 & 0x00FF0000) >> 16);
    pdata[i++] = ((arg1 & 0x0000FF00) >> 8);
    pdata[i++] = ((arg1 & 0x000000FF));

    pdata[i++] = ((arg2 & 0xFF000000) >> 24);
    pdata[i++] = ((arg2 & 0x00FF0000) >> 16);
    pdata[i++] = ((arg2 & 0x0000FF00) >> 8);
    pdata[i++] = ((arg2 & 0x000000FF));

    pdata[i++] = SOCKET_CMD_END;


    /* 设备IP xx.xx.xx.xx*/
    pdata[i++] = local_device_info.ip[3];
    pdata[i++] = local_device_info.ip[2];
    pdata[i++] = local_device_info.ip[1];
    pdata[i++] = local_device_info.ip[0];


    /* 发送端设备信息 type.unit.floor.index*/
    pdata[i++] = local_device_info.type;
    pdata[i++] = local_device_info.unit;
    pdata[i++] = local_device_info.floor;
    pdata[i++] = local_device_info.index;
    

    /* 接收端设备信息 type.unit.floor.index */
    pdata[i++] = (recvArg & 0xFF000000) >> 24;
    pdata[i++] = (recvArg & 0x00FF0000) >> 16;
    pdata[i++] = (recvArg & 0x0000FF00) >> 8;
    pdata[i++] = (recvArg & 0x000000FF);


    i = 60;
    i = 61;
    if (text) strncat(&pdata[i++], text, 64);


    for (int i = 0; i < sizeof(socket_cmd_recv_group) / sizeof(socket_cmd_recv_struct);i++){
        if (cmd == socket_cmd_recv_group[i].cmd){
            if (socket_cmd_recv_group[i].send_function != NULL){
                socket_cmd_recv_group[i].send_function(&info);
            }
            break;

        }
    }

    if(addr){
        user_socket_sendto(socket_cmd_send_fd, pdata, CMD_PACKAGE_LEN, addr, SOCKET_GROUP_PORT, 20);
    }else{
        user_socket_sendto(socket_cmd_send_fd, pdata, CMD_PACKAGE_LEN, SOCKET_GROUP_IP, SOCKET_GROUP_PORT, 20);

    }
    return i;
}




/**
 * @brief  解析数据
 * @date   2023-10-23 17:22:42
 * @author xiaole
 * @param  pdata
 * @return int
 * @note
 */
static int socket_cmd_recv_data_parase(const char *pdata){

    int i = 0;
    socket_cmd_send_device_struct info = {0};


    unsigned int senddevice = 0, recvdevice = 0;
    int ip[4] = {0};


    i++;
    info.cmd = pdata[i++];  //cmd = pdata[i++];

    info.arg1 |= pdata[i++] << 24;
    info.arg1 |= pdata[i++] << 16;
    info.arg1 |= pdata[i++] << 8;
    info.arg1 |= pdata[i++];
    info.arg2 |= pdata[i++] << 24;
    info.arg2 |= pdata[i++] << 16;
    info.arg2 |= pdata[i++] << 8;
    info.arg2 |= pdata[i++];

    i++;
    ip[3] = pdata[i++];
    ip[2] = pdata[i++];
    ip[1] = pdata[i++];
    ip[0] = pdata[i++];
    snprintf(info.addr, 16, "%d.%d.%d.%d", ip[3], ip[2], ip[1], ip[0]);


    senddevice |= pdata[i++] << 24;
    senddevice |= pdata[i++] << 16;
    senddevice |= pdata[i++] << 8;
    senddevice |= pdata[i++];
    recvdevice |= pdata[i++] << 24;
    recvdevice |= pdata[i++] << 16;
    recvdevice |= pdata[i++] << 8;
    recvdevice |= pdata[i++];






    i = 60;
    i = 61;
    strncat(info.text, &pdata[i], 64);

    printf("cmd=%d, arg1=%u, arg2=%u, text='%s', senddevice'%u', recvdevice'%u',addr='%s'\n",
           info.cmd, info.arg1, info.arg2, info.text, senddevice, recvdevice, info.addr);


    if (!(recvdevice == local_device_info.identifier || recvdevice == SOCKET_DEVICE_ALL)){
        return -1;
    }


    for (int i = 0; i < sizeof(socket_cmd_recv_group) / sizeof(socket_cmd_recv_struct);i++){
        if (info.cmd == socket_cmd_recv_group[i].cmd){
            if (socket_cmd_recv_group[i].recv_function != NULL){
                socket_cmd_recv_group[i].recv_function(&info);
            }
            break;

        }
    }


    return 1;
}


static void *socket_cmd_recv_thread_func(void *arg){

    while(1){
        usleep(1000);


        char recvbuffer[CMD_PACKAGE_LEN] = {0};
        int ret = user_socket_recv(socket_cmd_recv_fd, recvbuffer, sizeof(recvbuffer), 10);
        if(ret == CMD_PACKAGE_LEN){
            socket_cmd_recv_data_parase(recvbuffer);
        }

    }



    return NULL;

}


/**
 * @brief  初始化套接字
 * @date   2023-10-23 19:11:21
 * @author xiaole
 * @return int
 * @note
 */
int _network_device_init(){
    local_device_byname_refresh(SOCKET_DEVICE_TYPE_BOORBELL, OWNUNIT, OWNFLOOR, OWNINDEX);
    network_card_init(SOCKET_DEVICE_TYPE_BOORBELL);
    

    socket_cmd_send_init();
    socket_cmd_recv_init();



    pthread_t thread_cmd_recv_t;
    pthread_create(&thread_cmd_recv_t, NULL, socket_cmd_recv_thread_func, NULL);

    
    printf("network socket start\n");


    return 0;

}

